import { Injectable } from '@nestjs/common';
import { CreateRoleDto } from './dto/create-role.dto';
import { In, Repository } from 'typeorm';
import { Role } from 'src/database/entitys/role.entity';
import { InjectRepository } from '@nestjs/typeorm';
import { QueryRoleDto } from './dto/query-role.dto';
import { MenuRole } from 'src/database/entitys/menu-role.entity';
import { UpdateRoleMenuDto } from './dto/update-role-menu.dto';
import { Menu } from 'src/database/entitys/menu.entity';
import { UserRole } from 'src/database/entitys/user-role.entity';

@Injectable()
export class RoleService {
  constructor(
    @InjectRepository(Role)
    private roleRepository: Repository<Role>,
    @InjectRepository(MenuRole)
    private menuRoleRepository: Repository<MenuRole>,
    @InjectRepository(Menu)
    private menuRepository: Repository<Menu>,
    @InjectRepository(UserRole)
    private userRoleRepository: Repository<UserRole>
  ) {}

  /** 保存或修改角色 */
  async save(createRoleDto: CreateRoleDto) {
    return await this.roleRepository.save(createRoleDto);
  }

  /** 查询 */
  async findAll(queryRole: QueryRoleDto) {
    const { page = 1, size = 10, roleName } = queryRole;
    const queryBuilder = this.roleRepository
      .createQueryBuilder('role')
      .skip((page - 1) * size)
      .take(size);

    if (roleName && roleName.trim()) {
      queryBuilder.where('role.roleName LIKE :roleName', { roleName: `%${roleName.trim()}%` });
    }
    return await queryBuilder.getManyAndCount();
  }

  /** 更新角色菜单的关系 */
  async updateRoleMenu({ roleId, menuIds }: UpdateRoleMenuDto) {
    // 1. 查找角色
    const role = await this.roleRepository.findOneBy({ roleId: roleId });

    // 2. 删除现有的角色和菜单关联
    await this.menuRoleRepository.delete({ role: { roleId: roleId } });

    // 3. 根据新的菜单ID查找菜单
    const menus = await this.menuRepository.findBy({ menuId: In(menuIds) });

    // 4. 创建新的菜单角色关联
    const menuRoles = menus.map((menu) => {
      const menuRole = new MenuRole();
      menuRole.role = role;
      menuRole.menu = menu;
      return menuRole;
    });

    // 5. 保存新的菜单角色关联
    await this.menuRoleRepository.save(menuRoles);

    // 6. 返回更新后的角色信息
    return role;
  }

  /** 根据角色id获取角色菜单列表 */
  async findMenuListByRoleId(roleId: number) {
    // 1. 根据角色ID获取角色菜单关联列表
    const menuRoles = await this.menuRoleRepository.find({
      where: { role: { roleId: roleId } },
      relations: ['menu'],
    });

    // 2. 提取关联菜单列表
    const menus = menuRoles.map((menuRole) => menuRole.menu);

    return menus;
  }

  /** 通过角色标识查询 */
  async findByRoleKey(roleKey: string) {
    return await this.roleRepository.findOneBy({
      roleKey,
    });
  }

  /** 获取所有角色 */
  async getAllRole() {
    return await this.roleRepository.find();
  }

  /** 删除角色菜单关系 */
  async deleteRoleMenu(roleId: number) {
    return await this.menuRoleRepository.delete({ role: { roleId } });
  }

  /** 删除角色 */
  async deleteRole(roleId: number) {
    await this.deleteRoleMenu(roleId);
    await this.deleteRoleUser(roleId);
    return await this.roleRepository.delete(roleId);
  }

  /** 删除角色用户的关系 */
  async deleteRoleUser(roleId: number) {
    return await this.userRoleRepository.delete({ role: { roleId } });
  }
}
